#ifndef _B_PLUS_TREE_CACHE_HPP__
#define B_PLUS_TREE_CACHE_HPP__ 1
#include <BPlusTreeNodesStorage.hpp>
#include <BPlusTreeLeafsStorage.hpp>
#include <Hash.hpp>
#include <HashFunctions.hpp>
#include <BPlusNodeLeaf.hpp>
#include <list>
#define CLEAR_LEAFS_CACHE_SIZE 30000 
#define CLEAR_NODES_CACHE_SIZE 100000

/**
 * @class
 */
namespace FTSS{

	template <typename T, typename V, INT_64 TreeWidth>
	struct BPlusCacheWrapper{
		BPlusNodeType *pNodeType;
		std::list<INT_64>::iterator quePos;
		/**
		 * @brief Constructor
		 * @param pIleaf pointer to leaf
		 * @param iCurrentTick tick of creation
		 */
		BPlusCacheWrapper(BPlusNodeType *pINodeType/*, std::list<INT_64>::iterator it*/) : 
			pNodeType(pINodeType)/*, quePos(it)*/{}
		/**
		 * @brief Destructor
		 */
		~BPlusCacheWrapper(){
			if (pNodeType->id > 0){
				delete (BPlusNode<T, TreeWidth> *)pNodeType;
			} else {
				delete (BPlusLeaf<T, V, TreeWidth> *)pNodeType;
			}
		}
	};

	template <typename T, typename V, INT_64 TreeWidth>
	class BPlusCache{
		private:
			INT_64 tick;
			// hdd storages 
			FTSS::BPlusTreeNodeStorage *storage_nodes;
			FTSS::BPlusTreeLeafsStorage *storage_leafs;
			// memory caches 
			typename FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator>  *pCacheNodes;
			typename FTSS::Hash<INT_64, BPlusCacheWrapper<T, V, TreeWidth> *, HashHasher, HashComparator>  *pCacheLeafs;
			// LRU qeues
			std::list<INT_64> *nodesKeys;
			std::list<INT_64> *leafsKeys;
		public:
			/**
			 * @brief constructor
			 * @param node_storage_name - name of storage data nodes file
			 * @param node_storage_white_space_name - name of vector white space nodes storage
			 * @param leaf_storage_name - name of storage data leafs file
			 * @param leaf_storage_white_space_name - name of vector white space leafs storage
			 */
			BPlusCache(CCHAR_P node_storage_name,
				   CCHAR_P node_storage_white_space_name,
				   CCHAR_P leaf_storage_name,
				   CCHAR_P leaf_storage_white_space_name);
			
			/**
			 * @brief restore node or leaf from cache or hdd
			 * @param id - id
			 * @param memClear - true if can clear cash memory, false, if can't clear cash memory
			 */
			BPlusNodeType *getById(INT_64 id, bool memClear);

			/**
			 * @brief store node or leaf to HDD storage
			 * @param pNodeType - pointer to node or leaf to store
			 */
			INT_64 dumpNodeType(BPlusNodeType *pNodeType);

			/**
			 * @brief delete node or leaf from HDD
			 * @param pNodeType - pointer to node or leaf for delete
			 */
			void deleteNodeType(BPlusNodeType *pNodeType);

			/**
			 * @brief store metainformation about root of tree id to HDD storage
			 * @param root - id of root to store
			 */
			void dumpRootId(INT_64 root);

			/**
			 * @brief store metainformation about root of tree id to HDD storage
			 */
			INT_64 restoreRootId();

			/**
			 * @brief store metainformation about Tree Size to HDD storage
			 * @param TreeSize - tree size to store
			 */
			void dumpTreeSize(INT_64 TreeSize);

			/**
			 * @brief store metainformation about Tree Size to HDD storage
			 */
			INT_64 restoreTreeSize();

			/**
			 * @brief store metainformation about Tree Width to HDD storage
			 * @iTreeWidth - tree width to store
			 */
			void dumpTreeWidth(INT_64 iTreeWidth);

			/**
			 * @brief get metainformation about Tree Width from HDD storage 
			 */
			INT_64 restoreTreeWidth(); 
			/**
			 * @brief Destructor
			 */
			~BPlusCache() throw ();
		private:
			void clearMemory(INT_64 id);
	};
}
#include <BPlusCache.tcc>
#endif
